#ifndef _geometr_yh_
#define _geometr_yh_

// geometry.h
//
// Geometric classes for our classes

#include <utility>         // pair<>

namespace simple{   // short for Sharpmark IMage Processing Library E
    //
    // Pel Data Types
    //
    
    // It is very useful to keep pixel types separate to improve
    // readability and to make it easier to make changes.

    typedef unsigned char  Pel8;     // 1-byte
    typedef unsigned short Pel16;    // 2-bytes
    typedef int            Pel32s;   // 4-bytes  (Signed)
    typedef unsigned int   Pel32;    // 4-bytes  (Unsigned)

    //
    // min/max
    //
    template <class T> const T& Min (const T& a, const T& b)
    { return (a<b) ? a : b;}

    template <class T> const T& Max (const T& a, const T& b)
    { return (a>b) ? a : b;}

    //
    // Point
    //
    // The stl pair<> class comes close to what I want, but I want
    // it to look like a coordinate pair rather than two pieces of
    // data.
    class Point
    {
    public:
        Point () : _x (0), _y (0) {}
        Point (std::pair<int, int> p) : _x (p.first), _y (p.second) {}
        Point (int x, int y) : _x (x), _y (y) {}

        int x () const { return _x;}
        int y () const { return _y;}

        std::pair<int, int> point () const
        { return std::pair<int, int>(_x, _y);}

        bool  operator == (const Point& p) const
        { return x() == p.x() && y() == p.y();}

        Point& operator += (const Point& p)
        { _x += p.x(); _y += p.y(); return *this;}

        // Default copy constructor and assignment operators ok.
    private:
      int _x, _y;
    };


    class BString;  // Forward declaration.
    BString& operator<< (BString& stream, const Point& point);
    BString& operator>> (BString& stream, Point& point);

    //
    // Rect
    //
    class Rect
    {
    public:
      Rect ();
      Rect (Point ul, unsigned int width, unsigned int height);
      Rect (Point ul, Point lr);
      Rect (int x0, int y0, unsigned int width, unsigned int height);

      const Point& ul () const { return _ul;}
      Point        lr () const;
      // Returns upper-left and lower-right coordinates

      int  x0     () const { return _ul.x();}
      int  y0     () const { return _ul.y();}
      int  x1     () const { return lr().x();}
      int  y1     () const { return lr().y();}

      unsigned int  width  () const { return _width;}
      unsigned int  height () const { return _height;}

      bool  isNull () const { return _width == 0 || _height == 0;}
      // Returns true if the rectangle is null

      bool  operator == (const Rect& r) const;
      bool  operator != (const Rect& r) const
      { return !operator== (r);}
      // Returns true if this rectangle is identical

      bool  within (const Point& p) const;
      // Returns true if the point is within the rectangle判断点是否在矩形内部

      Rect intersect (const Rect& r) const;
      // Returns the intersection of two rectangles两个矩形的交集

      void expand (int x, int y);
      // Expand the size of the region in each dimension.
      // The width get 2x bigger, the height 2y bigger.
      // This can also be used to shrink a rectangle.
      // 将图像上下各扩展x, 左右扩展y

      // Default copy constructor and assignment operators ok.
    private:
      Point _ul;          // Upper-left hand coordinates
      unsigned int _width;  // Image width
      unsigned int _height; // Image height
    };


    BString& operator<< (BString& stream, const Rect& rect);
    BString& operator>> (BString& stream, Rect& rect);

}

#endif // _geometr_yh_
